package cn.edu.fudan.rule;

import cn.edu.fudan.data.*;
import cn.edu.fudan.tools.GetConfig;
import cn.edu.fudan.type.*;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by 80494 on 2017/4/19.
 */
public class WaveletRuleClassfierUCR {
    private static Logger logger = Logger.getLogger(WaveletRuleClassfierUCR.class);

    // public void WaveletRuleClassifierUCR (double support,double confidence){
    public static void main(String[] args) throws IOException {
        String datasetname = "Adiac";
        double support = 0.1;
        double confidence = 0.1;
        System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
        Config config;
        try {
            config = new GetConfig().getConfig();
            logger.info(config);

            String path = config.getPath();

            String filePath = path + datasetname;
            String trainPath = path + datasetname + "\\" + datasetname + "_TRAIN";
            String testPath = path + datasetname + "\\" + datasetname + "_TEST";
            //String trainPath = path + subject + "\\train.txt";
            //String testPath = path + subject + "\\test.txt";

            ReadData readData = new ReadData();
            ExtractFeature extractFeature = new ExtractFeature();
            HandelFeature handelFeature = new HandelFeature();
            SlideWindow slideWindow = new SlideWindow();
            HandleDistance handleDistance = new HandleDistance();
            WaveletPre waveletPre = new WaveletPre();
            RulePruning rulePruning = new RulePruning();
            RuleGeneration ruleGeneration = new RuleGeneration();
            Classifier classifier = new Classifier();

            List<List<DataItem>> database = new ArrayList<>();
            List<WaveletPerOrder> trainpre = new ArrayList<>();
            List<WaveletPerOrder> testpre = new ArrayList<>();
            List<Rule> ruleset = new ArrayList<>();

            int count = 0;
            double accuracy = 0.0;

            List<List<DataItem>> traindata = new ArrayList<>();
            List<List<DataItem>> testdata = new ArrayList<>();
            Integer trainclass_num = 0;
            Integer testclass_num = 0;
            int class_num = 0;

            try {
                TwoTuple<List<List<DataItem>>, Integer> traintwotuple = readData.readTimeFromUCRFormat(trainPath);
                TwoTuple<List<List<DataItem>>, Integer> testtwotuple = readData.readTimeFromUCRFormat(testPath);
                traindata = traintwotuple.first;
                System.out.println("Initial traindata success.");
                testdata = testtwotuple.first;
                System.out.println("Initial testdata success.");
                trainclass_num = traintwotuple.second;
                System.out.println("Initial train success.");
                testclass_num = testtwotuple.second;
                System.out.println("Initial test success.");
                class_num = Math.max(testclass_num, trainclass_num);
                System.out.println("Initial classnumber success.");
            } catch (Exception e) {
                e.printStackTrace();
                // TODO Auto-generated catch block e.printStackTrace();
            }
            if (traindata.size() > 0 && testdata.size() > 0 && class_num > 0) {
                long begin = System.currentTimeMillis();
                WaveletPerOrder trainpre_ele = new WaveletPerOrder();
                WaveletPerOrder testpre_ele = new WaveletPerOrder();
                System.out.println("Initial success.");

                for (int i = 0; i < traindata.size(); i++) {
                    trainpre_ele.setLabel((int)traindata.get(i).get(0).getValue());
                    traindata.get(i).remove(0);
                    trainpre_ele = waveletPre.WaveletPre(traindata.get(i));
                    //trainpre_ele.setLabel(0);
                    trainpre.add(trainpre_ele);
                }
                System.out.println("Traindata waveletpre success\n");

                long rulegenstart = System.currentTimeMillis();
                ruleset = ruleGeneration.RuleGeneration(trainpre, support, confidence, trainpre.size(), class_num);
                long rulegenend = System.currentTimeMillis();

                System.out.println("Rulegen success\n");

                TwoTuple<List<Rule>, Integer> twotuple = rulePruning.RulePruning(ruleset, trainpre, class_num);

                System.out.println("Ruleprune complete\n");
                for (int i = 0; i < testdata.size(); i++) {
                    testpre_ele.setLabel((int)testdata.get(i).get(0).getValue());
                    testdata.get(i).remove(0);
                    testpre_ele = waveletPre.WaveletPre(testdata.get(i));
                    //testpre_ele.setLabel(0);
                    testpre.add(testpre_ele);
                }
                System.out.println("Testdata waveletpre complete\n");

                for (int i = 0; i < testdata.size(); i++) {
                    if (classifier.Classifier(testdata.get(i), twotuple.first, twotuple.second) == testpre.get(i).getLabel()) {
                        count++;
                    }
                }

                //if(twotuple.first.size()==0) count=0; //没找到规则

                System.out.println("Classify complete\n");
                accuracy = (double) count / (double) testdata.size();

                long end = System.currentTimeMillis();
                logger.info("The support is set to " + support + ", and confidence is set to " + confidence);
                logger.info("Got " + ruleset.size() + "rules");
                logger.info("Run for " + (rulegenstart - rulegenend) / (double) 1000 + "seconds  for generate rule.");
                logger.info("Run for " + (end - begin) / (double) 1000 + "seconds.");
                logger.info("Accuracy is:" + accuracy);

            } else {
                System.out.println("Traindata is null or testdata is null or class_num==0");
            }

        } catch (IOException e1) { // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
}